#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>

typedef enum { false, true } bool;
typedef int Vertex; /* 顶点编号类型 */
#define kMaxVertex 10  /* 最大顶点数   */
typedef struct VertSetNode *VertexSet;
struct VertSetNode {
    bool *in; /* 顶点状态数组，true表示该顶点在解集里 */
    int n_verts; /* 顶点总个数 */
    int in_v; /* 当前解集中的顶点数 */
    int in_e; /* 当前解集覆盖的边数 */
    int E; /* 当前解的E值 */
};

typedef struct EdgeNode *Edges; /* 图中的边 */
struct EdgeNode {
    Vertex u, v; /* 边的两个端点 */
};

typedef struct EdgeSetNode *EdgeSet; /* 边集合 */
struct EdgeSetNode {
    Edges e; /* 存储边的数组 */
    int size; /* 集合规模 */
};

EdgeSet InitEdgeSet(int m) {
    /* 初始化一个空的边集合，最大容量为m */
    EdgeSet E;

    E = (EdgeSet)malloc(sizeof(struct EdgeSetNode));
    E->e = (Edges)malloc(sizeof(struct EdgeNode) * m);
    E->size = 0;
    return E;
}

VertexSet InitSet(int n) {
    /* 初始化一个空的解集 */
    VertexSet s;
    int i;

    s = (VertexSet)malloc(sizeof(struct VertSetNode));
    s->in = (bool *)malloc(sizeof(bool) * n);
    for (i = 0; i < n; i++) {
        s->in[i] = false;
    }
    s->n_verts = n;
    s->in_v = 0;
    s->in_e = 0;
    s->E = 0;

    return s;
}

double Random(double a, double b) {
    /* 生成 [a,b] 区间内的随机数 */
    double t;

    t = (double)rand() / RAND_MAX; /* 生成 [0,1] 区间内的随机数 */
    return (a + t * (b - a));
}

int E(Vertex v, VertexSet s, EdgeSet Edge) {
    /* 能量函数 E = 点数 - 边数*2 */
    int e_cnt, ret, n, m, i;
    Vertex u;

    n = s->in_v; /* 当前解s中收录的顶点数 */
    m = Edge->size; /* 图中的边数 */
    e_cnt = 0; /* 统计将v加入/删除解集后新增/减少覆盖的边数 */
    for (i = 0; i < m; i++) { /* 检查每一条边 */
        if (Edge->e[i].u == v
        || Edge->e[i].v == v) { /* 如果该边的一个端点是v */
            /* 令u为该边的另一个端点 */
            if (Edge->e[i].v == v) {
                u = Edge->e[i].u;
            } else {
                u = Edge->e[i].v;
            }
            if (s->in[u] == false) { /* 若另一端u不在解集中 */
                if (s->in[v] == false) { /* v之前不在解集中 */
                    e_cnt++; /* 收录v意味着加边 */
                } else { /* v之前在解集中 */
                    e_cnt--; /* 删除v意味着减边 */
                }
            }
        }
    }
    if (s->in[v] == false) { /* v之前不在解集中 */
        ret = (n + 1) - ((s->in_e + e_cnt) << 1);
    } else { /* v之前在解集中 */
        ret = (n - 1) - ((s->in_e + e_cnt) << 1);
    }
    return ret;
}

void Accept(VertexSet current_solution, Vertex next_solution, int dE) {
    /* 将 next_solution 收入或删除，更新 current_solution */
    if (current_solution->in[next_solution] ==
                false) { /* next_solution 之前不在解集中 */
        current_solution->in[next_solution] = true; /* next_solution加入 */
        current_solution->in_v++; /* 解集顶点数加 1 */
    } else { /* next_solution 之前在解集中 */
        current_solution->in[next_solution] = false; /* next_solution删除 */
        current_solution->in_v--; /* 解集顶点数减 1 */
    }
    current_solution->E += dE; /* 更新当前解的E值 */
    /* 根据顶点数和E值反推当前解覆盖的边数，避免重复计算 */
    current_solution->in_e = (current_solution->in_v - current_solution->E) >> 1;
}

/* 算法16-6：模拟退火算法 SimulatedAnnealing(init_solution, E, T, alpha, k, iter_num, eps) */
void SimulatedAnnealing(VertexSet init_solution,
                        int (*E)(Vertex v, VertexSet s, EdgeSet Edge),
                        double T, double alpha, double k, int iter_num, double eps,
                        EdgeSet Edge) {
    VertexSet current_solution;
    Vertex next_solution;
    double pr;
    int dE, n, i;

    n = init_solution->n_verts; /* 图中的顶点数 */
    current_solution = init_solution;
    srand((unsigned)time(NULL)); /* 为随机数产生种子 */
    while (T >= eps) {
        for (i = 0; i < iter_num; i++) { /* 每迭代iter_num次进行一次降温 */
            next_solution = (int)Random(0,
                                        n - 1); /* 在当前解的邻域内随机选择一个解 */
            dE = E(next_solution, current_solution, Edge) - current_solution->E;
            if (dE < 0) { /* 若新解比当前解更好，则接受新解 */
                Accept(current_solution, next_solution, dE);
            } else { /* 若新解比当前解差 */
                pr = exp(-dE / (k * T)); /* 以概率pr接受新解作为当前解 */
                if (Random(0, 1) < pr) {
                    Accept(current_solution, next_solution, dE);
                }
            }
        }
        T *= alpha; /* 温度参数T以系数alpha减小 */
    }
}
/* 算法16-6 结束 */

int main(void) {
    VertexSet solution;
    EdgeSet Edge;
    Vertex u, v;
    double T, alpha, k, eps;
    int n, m, iter_num, i;

    scanf("%d %d", &n, &m);
    Edge = InitEdgeSet(m);
    for (i = 0; i < m; i++) {
        scanf("%d %d", &u, &v);
        Edge->e[Edge->size].u = u;
        Edge->e[Edge->size].v = v;
        Edge->size++;
    }
    solution = InitSet(n);
    scanf("%lf %lf %lf %d %lf", &T, &alpha, &k, &iter_num, &eps);
    SimulatedAnnealing(solution, E, T, alpha, k, iter_num, eps, Edge);
    for (v = 0; v < n; v++) {
        if (solution->in[v] == true) {
            printf("%d ", v);
        }
    }

    return 0;
}